package com.jy.oms.framework.asyn.task.handler;

import com.jy.oms.framework.asyn.task.annotation.Task;
import com.jy.oms.framework.asyn.task.exception.TaskNeverRetryException;
import com.jy.oms.framework.asyn.task.model.TaskDto;
import com.jy.oms.framework.asyn.task.model.TaskLogDto;
import com.jy.oms.framework.asyn.task.queue.TaskQueueManagerProxy;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 * 任务切面
 *
 * @author liuquan
 */
@Component
@Aspect
public class TaskAspectHandler {
    private static Logger logger = LoggerFactory.getLogger(TaskAspectHandler.class);

    @Around(value = "@annotation(task)")
    public Object around(ProceedingJoinPoint joinPoint, Task task) throws Throwable {
        Object param = joinPoint.getArgs() != null && joinPoint.getArgs().length == 1 ? joinPoint.getArgs()[0] : null;
        if (param == null) {
            logger.warn("【" + task.taskCode() + "】任务参数不合法");
        }

        //是否由MethodTaskHandler触发执行
        boolean isMethodTaskHandlerCall = MethodTaskHandlerThreadLocal.get();
        boolean isDirectCall = !isMethodTaskHandlerCall && param != null;

        if (isDirectCall && task.saveAndAsyncExecuteWhenDirectCall()) {
            //先保存任务异步执行
            TaskDto taskDto = new TaskDto();
            taskDto.setTaskCode(task.taskCode());
            taskDto.setParam(param);
            TaskQueueManagerProxy.addTask(taskDto);
        } else {
            long begin = System.currentTimeMillis();
            try {
                Object result = joinPoint.proceed();

                //直接调用执行任务，完成时记录日志
                if (isDirectCall) {
                    TaskLogDto taskLogDto = new TaskLogDto();
                    taskLogDto.setTaskCode(task.taskCode());
                    taskLogDto.setParam(param);
                    taskLogDto.setResponse(result);
                    taskLogDto.setCostTime(System.currentTimeMillis() - begin);
                    TaskQueueManagerProxy.insertTaskLog(taskLogDto);
                }

                return result;
            } catch (Throwable throwable) {
                if (throwable instanceof TaskNeverRetryException) {
                    TaskNeverRetryException e = (TaskNeverRetryException) throwable;
                    if (e.isSaveLog()) {
                        TaskLogDto taskLogDto = new TaskLogDto();
                        taskLogDto.setTaskCode(task.taskCode());
                        taskLogDto.setParam(param);
                        taskLogDto.setResponse(e.getMessage());
                        taskLogDto.setCostTime(System.currentTimeMillis() - begin);
                        TaskQueueManagerProxy.insertTaskLog(taskLogDto);
                    }
                } else {
                    if (isDirectCall) {
                        TaskDto taskDto = new TaskDto();
                        taskDto.setTaskCode(task.taskCode());
                        taskDto.setParam(param);
                        TaskQueueManagerProxy.addTask(taskDto);

                        logger.error("【" + task.taskCode() + "】异常重试", throwable);
                    } else {
                        throw throwable;
                    }
                }
            }
        }

        return null;
    }
}
